from tqsdk.ta import MA,BOLL
from time import time
def is_descending(lst):#大到小排列
    return all(lst[i] >= lst[i+1] for i in range(len(lst)-1))
def is_increasing(lst):#小到大排列
    return all(lst[i] <= lst[i+1] for i in range(len(lst)-1))
def 均线排列_小时(productInfo):
    strategyID=1
    strategyBool=False
    if strategyID not in productInfo['alertTimeDict']:productInfo['alertTimeDict'][strategyID]=0
    frozenDuration=60*3
    frozen_flag=time()-productInfo['alertTimeDict'][strategyID]>frozenDuration
    if not frozen_flag:return False,strategyID,''
    msg='''一小时K线均线多头排列，5分钟K线空头排列'''
    if 'K_h' not in productInfo:return False,strategyID,'无 K_h '
    H_ma_5=MA(productInfo['K_h'],5)
    H_ma_10=MA(productInfo['K_h'],10)
    H_ma_20=MA(productInfo['K_h'],20)
    H_ma_40=MA(productInfo['K_h'],40)
    index=-2  #符合条件的周期数
    while 1:#多头排列
        if is_descending([H_ma_5.iloc[index]['ma'],H_ma_10.iloc[index]['ma'],H_ma_20.iloc[index]['ma'],H_ma_40.iloc[index]['ma']]):  
            index=index-1
        else:
            break
    H_Kline_duoPai_flag=index<-7
    index=-2  #符合条件的周期数
    while 1:#空头排列
        if is_increasing([H_ma_5.iloc[index]['ma'],H_ma_10.iloc[index]['ma'],H_ma_20.iloc[index]['ma'],H_ma_40.iloc[index]['ma']]):  
            index=index-1
        else:
            break
    H_Kline_kongPai_flag=index<-7
    #既不是多头排列，也不是空头排列，return
    if not (H_Kline_duoPai_flag or H_Kline_kongPai_flag):return False,strategyID,''

    min5_ma_5=MA(productInfo['K_5min'],5)
    min5_ma_10=MA(productInfo['K_5min'],10)
    min5_ma_20=MA(productInfo['K_5min'],20)
    min5_ma_40=MA(productInfo['K_5min'],40)
    index=-2  #符合条件的周期数
    while 1:  #空头排列
        if is_increasing([min5_ma_5.iloc[index]['ma'],min5_ma_10.iloc[index]['ma'],min5_ma_20.iloc[index]['ma'],min5_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    min5_Kline_kongPai_flag=index<-4
    index=-2  #符合条件的周期数
    while 1:  #多头排列
        if is_descending([min5_ma_5.iloc[index]['ma'],min5_ma_10.iloc[index]['ma'],min5_ma_20.iloc[index]['ma'],min5_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    min5_Kline_duoPai_flag=index<-4
    if H_Kline_duoPai_flag and min5_Kline_kongPai_flag:
        msg='''H K线均线多头排列，5分钟K线空头排列'''
        strategyBool=True
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    if H_Kline_kongPai_flag and min5_Kline_duoPai_flag:
        msg='''H K线均线空头排列，5分钟K线多头排列'''
        strategyBool=True
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    
    strategyID=3
    boll=BOLL(productInfo['K_5min'], 14, 2.5)
    highThanTop=productInfo['K_5min'].iloc[-1]['close']>boll.iloc[-1]['top']
    lowThanBottom=productInfo['K_5min'].iloc[-1]['close']<boll.iloc[-1]['bottom']
    if H_Kline_kongPai_flag and highThanTop:
        msg='''H K线均线空头排列，5分钟K线超布林线上轨'''
        strategyBool=True
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    if H_Kline_duoPai_flag and lowThanBottom:
        msg='''H K线均线多头排列，5分钟K线超布林线下轨'''
        strategyBool=True
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    #如果都不符合，则返回False
    return False,strategyID,''  
def beili_2(productInfo):
    '''15min k线多/空头排列持续7个周期，与，当前K线上涨背离 '''
    strategyID=2
    strategyBool=False
    if strategyID not in productInfo['alertTimeDict']:productInfo['alertTimeDict'][strategyID]=0
    frozenDuration=60*2
    frozen_flag=time()-productInfo['alertTimeDict'][strategyID]>frozenDuration
    if not frozen_flag:return False,strategyID,''
    min15_ma_5=MA(productInfo['K_15min'],5)
    min15_ma_10=MA(productInfo['K_15min'],10)
    min15_ma_20=MA(productInfo['K_15min'],20)
    min15_ma_40=MA(productInfo['K_15min'],40)
    lastKline=productInfo['K_15min'].iloc[-1]
    index=-2  #符合条件的周期数
    while 1:  #空头排列
        if is_increasing([min15_ma_5.iloc[index]['ma'],min15_ma_10.iloc[index]['ma'],min15_ma_20.iloc[index]['ma'],min15_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    min15_Kline_kongPai_flag=index<-7
    index=-2  #符合条件的周期数
    while 1:  #多头排列
        if is_descending([min15_ma_5.iloc[index]['ma'],min15_ma_10.iloc[index]['ma'],min15_ma_20.iloc[index]['ma'],min15_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    min15_Kline_duoPai_flag=index<-7
    if not (min15_Kline_duoPai_flag or min15_Kline_kongPai_flag):return False,strategyID,''
    height=(lastKline['close']-lastKline['open'])/productInfo['miniPrice']
    if min15_Kline_duoPai_flag and height<-7:
        strategyBool=True
        msg='''15min k线多头排列7个周期，与当前K线下跌背离 '''
        # productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    if min15_Kline_kongPai_flag and height>7:
        strategyBool=True
        msg='''15min k线空头排列7个周期，与当前K线上涨背离 '''
        # productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    
    return False,strategyID,''
def 日K排列(productInfo):
    strategyID=0
    strategyBool=False
    if strategyID not in productInfo['alertTimeDict']:productInfo['alertTimeDict'][strategyID]=0
    frozenDuration=60*15
    frozen_flag=time()-productInfo['alertTimeDict'][strategyID]>frozenDuration
    if not frozen_flag:return False,strategyID,''

    #  K_day
    day_ma_5=MA(productInfo['K_day'],5)
    day_ma_10=MA(productInfo['K_day'],10)
    day_ma_20=MA(productInfo['K_day'],20)
    day_ma_40=MA(productInfo['K_day'],40)
    index=-2  #符合条件的周期数
    while 1:  #空头排列
        if is_increasing([day_ma_5.iloc[index]['ma'],day_ma_10.iloc[index]['ma'],day_ma_20.iloc[index]['ma'],day_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    day_Kline_kongPai_flag=index<-4
    index=-2  #符合条件的周期数
    while 1:  #空头排列
        if is_descending([day_ma_5.iloc[index]['ma'],day_ma_10.iloc[index]['ma'],day_ma_20.iloc[index]['ma'],day_ma_40.iloc[index]['ma']]):  #多头排列
            index=index-1
        else:
            break
    day_Kline_duoPai_flag=index<-4
    if not (day_Kline_duoPai_flag or day_Kline_kongPai_flag):return False,strategyID,''
    lastKlineHeight=(productInfo['K_day'].iloc[-1]['close']-productInfo['K_day'].iloc[-1]['open'])/productInfo['miniPrice']
    if day_Kline_kongPai_flag and lastKlineHeight>40:
        strategyBool=True
        msg='''日k线空头排列5个周期，当前K线上涨回调 '''
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    if day_Kline_duoPai_flag and lastKlineHeight<-40:
        strategyBool=True
        msg='''日k线多头排列5个周期，当前K线下跌回调 '''
        productInfo['alertTimeDict'][strategyID]=time()
        return strategyBool,strategyID,msg
    return False,strategyID,''
def 均线宽度(productInfo):
    strategyID=3
    if strategyID not in productInfo['alertTimeDict']:productInfo['alertTimeDict'][strategyID]=0
    frozenDuration=60*3
    frozen_flag=time()-productInfo['alertTimeDict'][strategyID]>frozenDuration
    if not frozen_flag:return False,strategyID,''
    miniPrice=productInfo['miniPrice']
    min5_ma_5=MA(productInfo['K_5min'],5)
    min5_ma_40=MA(productInfo['K_5min'],40)
    kuan=abs(min5_ma_5.iloc[-1]['ma']-min5_ma_40.iloc[-1]['ma'])/miniPrice
    if kuan>10:

        return True,strategyID,'均线宽度=%f'%kuan
    return False,strategyID,''
def getHeight(kilineObj,index=-1):
    return kilineObj.iloc[index]['close']-kilineObj.iloc[index]['open']
def minK(productInfo):
    '''一分钟均线，高度和排列'''
    strategyID=4
    frozenDuration=60
    if strategyID not in productInfo['alertTimeDict']:productInfo['alertTimeDict'][strategyID]=0
    frozen_flag=time()-productInfo['alertTimeDict'][strategyID]>frozenDuration
    if not frozen_flag:return False,strategyID,''
    min_ma_5=MA(productInfo['K_min'],5)
    min_ma_10=MA(productInfo['K_min'],10)
    min_ma_20=MA(productInfo['K_min'],20)
    min_ma_40=MA(productInfo['K_min'],40)

    index=-1
    H_Kline_duoPai_flag=is_descending([min_ma_5.iloc[index]['ma'],min_ma_10.iloc[index]['ma'],min_ma_20.iloc[index]['ma'],min_ma_40.iloc[index]['ma']])
    H_Kline_kongPai_flag=is_increasing([min_ma_5.iloc[index]['ma'],min_ma_10.iloc[index]['ma'],min_ma_20.iloc[index]['ma'],min_ma_40.iloc[index]['ma']])
    #既不是多头排列，也不是空头排列，return
    if not (H_Kline_duoPai_flag or H_Kline_kongPai_flag):return False,strategyID,''

    curMinHeight=getHeight(productInfo['K_min'],index=-1)
    #均线宽度不能太大
    junxianKuan=abs(round((min_ma_5.iloc[-1]['ma']-min_ma_40.iloc[-1]['ma'])/productInfo['miniPrice']))
    # print(productInfo['IntrumentID'],H_Kline_duoPai_flag,junxianKuan,curMinHeight/productInfo['miniPrice'])
    if junxianKuan<productInfo['PaiLieKuanDu'] :
        return False,strategyID,''
    elif H_Kline_duoPai_flag : 
        return True,strategyID,'1分钟 多头排列 宽度%d'%junxianKuan
    elif H_Kline_kongPai_flag: 
        return True,strategyID,'1分钟 空头排列 宽度%d'%junxianKuan
    return False,strategyID,''
def startegyHandle(productInfo):
    #通用策略
    strategyBool,strategyID,msg=minK(productInfo)
    if strategyBool:return strategyID,msg